package com.example.springboot.task.async.controller;

import com.example.springboot.task.async.service.AsyncService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @Author:ChenZhangKun
 * @Date: 2020/10/27 20:02
 */
@RestController
@Slf4j
public class AsyncController {
    @Autowired
    private AsyncService asyncService;

    @GetMapping("/hello")
    public String sayHello() {
        try {
            asyncService.hello();
            // 测试支持注解的spel表达式
            asyncService.testSpel();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "success";
    }

    @GetMapping("/hello2")
    public String sqyHello_2() {
        String hello2 = "";
        try {
            hello2 = asyncService.hello_2();
            // Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return hello2;
    }

    @GetMapping("/hello3")
    public void test() throws Exception {
        Long start = System.currentTimeMillis();
        CompletableFuture<String> one = asyncService.doTaskOne();
        CompletableFuture<String> two = asyncService.doTaskTwo();
        CompletableFuture<String> three = asyncService.doTaskThree();
        CompletableFuture<Void> all = CompletableFuture.allOf(one, two, three);
        all.join();
        Long end = System.currentTimeMillis();
        // 此时总耗时会比各个任务耗时加起来少
        log.info("任务全部完成，总耗时：" + (end - start) + "毫秒");
    }

    //@Bean
    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(1);
        threadPoolTaskExecutor.setMaxPoolSize(1);
        threadPoolTaskExecutor.setThreadNamePrefix("czk-");
        /**
         * AbortPolicy策略：默认策略，如果线程池队列满了丢掉这个任务并且抛出RejectedExecutionException异常。
         * DiscardPolicy策略：如果线程池队列满了，会直接丢掉这个任务并且不会有任何异常。
         * DiscardOldestPolicy策略：如果队列满了，会将最早进入队列的任务删掉腾出空间，再尝试加入队列。
         * CallerRunsPolicy策略：如果添加到线程池失败，那么主线程会自己去执行该任务，不会等待线程池中的线程去执行。
         */
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
/*        // 自定义线程池拒绝策略
        threadPoolTaskExecutor.setRejectedExecutionHandler((r,executor)->{
            // 执行自定义的拒绝策略
        });*/
        return threadPoolTaskExecutor;
    }

}
